package jp.co.dailyReport.staff;

import java.sql.SQLException;
import org.apache.log4j.Logger;
import jp.co.dailyReport.ExecuterManager;
import jp.co.dailyReport.staff.sql.StaffDeleteExecuter;
import jp.co.dailyReport.staff.sql.StaffLoadExecuter;
import jp.co.dailyReport.staff.sql.StaffInsertExecuter;
import jp.co.dailyReport.staff.sql.StaffUpdateExecuter;
import jp.co.dailyReport.staff.sql.StaffUsrLoadExecuter;
import jp.co.dailyReport.staff.sql.StaffsLoadExecuter;
import jp.co.dailyReport.staff.sql.ProjectListLoadExecuter;
import jp.co.dailyReport.ConnectionFactory;
import jp.co.dailyReport.DataUnavailableException;
import jp.co.dailyReport.PermissionManager;
import jp.co.dailyReport.PermissionException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 社員情報管理クラス
 */
public class StaffManager {

	private static Logger log = Logger.getLogger(StaffManager.class);

	/**
	 * 社員情報を取得します。
	 * 
	 * @return 社員オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static Staff[] load() throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffsLoadExecuter staffsLoadExecuter = new StaffsLoadExecuter();
		Object objs[] = (Object[])null;
		try {
            objs = ExecuterManager.execute(connectionFactory, staffsLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new Staff[0];
		} else {
			return (Staff[])objs;
		}
	}

	/**
	 * 社員の権限で社員情報を取得します。
	 * 
	 * @param staff 社員オブジェクト
	 * @return 社員オブジェクトの配列
	 * @throws DataUnavailableException、PermissionException 権限が無いときに発生します。
	 */
	public static Staff[] load(Staff staff)
		 throws DataUnavailableException ,PermissionException{

		Staff[] staffs = null;
		//社員情報登録権限の判定
		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_REGISTRATION,PermissionManager.METHOD_READ)){
			if(staffs==null) staffs = load();
		}
		//社員情報更新権限の判定
		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_UPDATE,PermissionManager.METHOD_READ)){
			if(staffs==null) staffs = load();
		}
		//社員情報削除権限の判定
		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_DELETE,PermissionManager.METHOD_READ)){
			if(staffs==null) staffs = load();
		}
		if(staffs==null) {
			throw new PermissionException("Permission denied to all functions staff");
		}
		return staffs;
	}

	/**
	 * 社員情報を取得します。
	 * 
	 * @param staffId 社員ID
	 * @return 社員オブジェクト
	 * @throws DataUnavailableException
	 */
	public static Staff load(int staffId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffLoadExecuter staffLoadExecuter = new StaffLoadExecuter(staffId);
		Object objs[] = (Object[])null;
		try {
			objs = ExecuterManager.execute(connectionFactory, staffLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new Staff();
		} else {
			return (Staff)objs[0];
		}
	}

	/**
	 * 社員情報を取得します。
	 * 
	 * @param usr ユーザID
	 * @return 社員オブジェクト
	 * @throws DataUnavailableException
	 */
	public static Staff load(String usr) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffUsrLoadExecuter staffUsrLoadExecuter = new StaffUsrLoadExecuter(usr);
		Object objs[] = (Object[])null;
		try {
			objs = ExecuterManager.execute(connectionFactory, staffUsrLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
            return new Staff();
		} else {
			return (Staff)objs[0];
		}
	}

	/**
	 * 社員情報を更新します。
	 * 
	 * @param staff 社員オブジェクト
	 * @throws DataUnavailableException
	 */
	public static void update(Staff staff) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffUpdateExecuter staffUpdateExecuter = new StaffUpdateExecuter(staff);
		try {
			ExecuterManager.execute(connectionFactory, staffUpdateExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 社員の権限で社員情報を更新します。
	 * 
	 * @param staff 社員オブジェクト
	 * @param targetStaff 社員オブジェクト(更新される)
	 * @throws DataUnavailableException、PermissionException 権限が無いときに発生します。
	 */
	public static void update(Staff staff,Staff targetStaff) throws DataUnavailableException ,PermissionException{

		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_UPDATE,PermissionManager.METHOD_WRITE)){
			update(targetStaff);
		} else {
			throw new PermissionException("Permission denied to update staff");
		}
	}

	/**
	 * 社員情報を登録します。
	 * 
	 * @param staff 社員オブジェクト
	 * @throws DataUnavailableException
	 */
	public static void insert(Staff staff) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffInsertExecuter staffInsertExecuter = new StaffInsertExecuter(staff);
		try {
			ExecuterManager.execute(connectionFactory, staffInsertExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 社員の権限で社員情報を登録します。
	 * 
	 * @param staff 社員オブジェクト
	 * @param targetStaff 社員オブジェクト(登録される)
	 * @throws DataUnavailableException、PermissionException 権限が無いときに発生します。
	 */
	public static void insert(Staff staff,Staff targetStaff)
		 throws DataUnavailableException ,PermissionException{

		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_REGISTRATION,PermissionManager.METHOD_WRITE)){
			insert(targetStaff);
		}else{
			throw new PermissionException("Permission denied to insert staff");
		}
	}

	/**
	 * 社員情報を削除します。
	 * 
	 * @param staffId 社員ID
	 * @throws DataUnavailableException
	 */
	public static void delete(int staffId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		StaffDeleteExecuter staffDeleteExecuter = new StaffDeleteExecuter(staffId);
		try {
			ExecuterManager.execute(connectionFactory, staffDeleteExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 社員の権限で社員情報を削除します。
	 * 
	 * @param staff 社員オブジェクト
	 * @param targetStaffId 社員ID
	 * @throws DataUnavailableException、PermissionException 権限が無いときに発生します。
	 */
	public static void delete(Staff staff ,int targetStaffId) throws DataUnavailableException ,PermissionException{

		if(PermissionManager.hasPermission(staff,PermissionManager.STAFF_DELETE,PermissionManager.METHOD_WRITE)){
			delete(targetStaffId);
		} else {
			throw new PermissionException(" Permission denied to delete staff");
		}
	}

	/**
	 * 社員情報の存在チェックを行います。
	 * 
	 * @param usr ユーザID
	 * @return true→存在する、false→存在しない
	 * @throws DataUnavailableException
	 */
    public static boolean isExist(String usr) throws DataUnavailableException {

		Staff staff = load(usr);
		if(staff.getStaffId() == 0){
			return false;
		} else {
			return !staff.isDelFlg();
		}
	}

	/**
	 * プロジェクトリーダーであるかのチェックを行います。
	 * 
	 * @param staff 社員オブジェクト
	 * @return true→プロジェクトリーダーである、false→プロジェクトリーダーでない
	 * @throws DataUnavailableException
	 */
	public static boolean isProjectLeader(Staff staff) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		ProjectListLoadExecuter projectListLoadExecuter = new ProjectListLoadExecuter(staff);
		Object objs[] = (Object[])null;
		try {
			objs = ExecuterManager.execute(connectionFactory, projectListLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		return objs != null && objs.length != 0;
	}

	/**
	 * 引数となる文字列のハッシュ値を求めます。
	 * 
	 * @param str 文字列
	 * @return 引数の文字列のハッシュ値
	 * @throws DataUnavailableException、PermissionException 権限が無いときに発生します。
	 */
	public static String encryptedPassword(String str) throws DataUnavailableException {

		String encryptedPassword = "";
		try{
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			byte[] md5Password = md5.digest(str.getBytes());
			for(int i=0;i<md5.digest(str.getBytes()).length;i++){
				encryptedPassword += Integer.toHexString((int)md5Password[i]);
			}
		} catch (NoSuchAlgorithmException nsae) {
			throw new DataUnavailableException(nsae.toString());
		}
		return encryptedPassword;
	}
}
